import os
import shutil
from datetime import datetime
from fastapi import APIRouter, Depends, File, UploadFile, Query
from sqlalchemy.orm import Session

from api.database import get_db
from api.model.user import User
from api.model.email_account import EmailAccount
from api.model.draft import Draft
from api.controller.auth import get_current_user
from api.utils.response import success, fail
from api.utils.logger import get_logger
from api.utils.async_helper import run_in_executor

logger = get_logger("upload")

router = APIRouter()


@router.post("")
async def upload_file(
    file: UploadFile = File(...),
    type: str = Query(..., description="上传类型: avatar, image, draft"),
    id: int = Query(None, description="草稿ID（type=draft时必填）"),
    account_id: int = Query(None, description="账户ID（type=image或draft时必填）"),
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    统一文件上传接口
    
    参数说明：
    - type: 上传类型
      * avatar: 头像上传
      * image: 编辑器图片上传
      * draft: 草稿附件上传
    - id: 草稿ID（仅type=draft时需要）
    - account_id: 邮箱账户ID（type=image或draft时需要）
    """
    try:
        # 根据type进行不同的处理
        if type == "avatar":
            return await upload_avatar(file, current_user, db)
        elif type == "image":
            if not account_id:
                return fail("上传编辑器图片需要提供account_id参数")
            return await upload_editor_image(file, account_id, current_user, db)
        elif type == "draft":
            if not account_id or not id:
                return fail("上传草稿附件需要提供account_id和id参数")
            return await upload_draft_attachment(file, account_id, id, current_user, db)
        else:
            return fail(f"不支持的上传类型: {type}")
    except Exception as e:
        logger.error(f"文件上传失败: {str(e)}", exc_info=True)
        return fail(f"文件上传失败: {str(e)}")


async def upload_avatar(file: UploadFile, current_user: User, db: Session):
    """
    上传头像
    存储路径: uploads/avatars/{user_id}_{timestamp}.{ext}
    """
    # 验证文件类型
    if file.content_type not in ["image/jpeg", "image/png", "image/gif"]:
        return fail("只支持上传 JPG, PNG, GIF 格式的图片")
    
    # 限制大小为 2MB
    content = await file.read()
    if len(content) > 2 * 1024 * 1024:
        return fail("图片大小不能超过 2MB")
    
    # 创建上传目录
    upload_dir = "uploads/avatars"
    await run_in_executor(os.makedirs, upload_dir, exist_ok=True)
    
    # 生成唯一文件名
    file_extension = os.path.splitext(file.filename)[1]
    unique_filename = f"{current_user.id}_{datetime.now().strftime('%Y%m%d%H%M%S')}{file_extension}"
    file_path = os.path.join(upload_dir, unique_filename)
    
    # 保存文件 - 异步执行
    def write_file():
        with open(file_path, "wb") as buffer:
            buffer.write(content)
    await run_in_executor(write_file)
    
    # 更新用户头像URL为相对路径
    avatar_url = f"/uploads/avatars/{unique_filename}"
    current_user.avatar = avatar_url
    db.commit()
    db.refresh(current_user)
    
    logger.info(f"用户 {current_user.id} 上传头像成功: {file_path}")
    return success(data={
        "path": file_path,
        "filename": unique_filename,
        "url": avatar_url,
        "avatar_url": avatar_url  # 兼容旧接口
    }, msg="头像上传成功")


async def upload_editor_image(file: UploadFile, account_id: int, current_user: User, db: Session):
    """
    上传编辑器图片
    存储路径: uploads/images/{timestamp}_{random}.{ext}
    """
    # 验证账户权限
    account = db.query(EmailAccount).filter(
        EmailAccount.id == account_id,
        EmailAccount.user_id == current_user.id
    ).first()
    if not account:
        return fail("邮箱账户未找到")
    
    # 验证文件类型
    if not file.content_type or not file.content_type.startswith("image/"):
        return fail("只支持上传图片格式")
    
    # 限制大小为 5MB
    content = await file.read()
    if len(content) > 5 * 1024 * 1024:
        return fail("图片大小不能超过 5MB")
    
    # 创建上传目录
    upload_dir = "uploads/images"
    await run_in_executor(os.makedirs, upload_dir, exist_ok=True)
    
    # 生成唯一文件名
    file_extension = os.path.splitext(file.filename)[1]
    unique_filename = f"{datetime.now().strftime('%Y%m%d%H%M%S')}_{os.urandom(8).hex()}{file_extension}"
    file_path = os.path.join(upload_dir, unique_filename)
    
    # 保存文件 - 异步执行
    def write_file():
        with open(file_path, "wb") as buffer:
            buffer.write(content)
    await run_in_executor(write_file)
    
    # 返回相对于 web 根目录的相对路径
    url = f"/uploads/images/{unique_filename}"
    
    logger.info(f"账户 {account_id} 上传编辑器图片成功: {file_path}")
    return success(data={
        "path": file_path,
        "filename": unique_filename,
        "url": url
    }, msg="图片上传成功")


async def upload_draft_attachment(file: UploadFile, account_id: int, draft_id: int, current_user: User, db: Session):
    """
    上传草稿附件
    存储路径: runtime/files/drafts/{draft_id}/{filename}
    """
    # 验证账户权限
    account = db.query(EmailAccount).filter(
        EmailAccount.id == account_id,
        EmailAccount.user_id == current_user.id
    ).first()
    if not account:
        return fail("邮箱账户未找到")
    
    # 验证草稿权限
    draft = db.query(Draft).filter(
        Draft.id == draft_id,
        Draft.email_account_id == account_id
    ).first()
    if not draft:
        return fail("草稿未找到")
    
    # 限制大小为 10MB
    content = await file.read()
    if len(content) > 10 * 1024 * 1024:
        return fail("附件大小不能超过 10MB")
    
    # 创建草稿附件目录
    draft_dir = os.path.join("runtime", "files", "drafts", str(draft_id))
    await run_in_executor(os.makedirs, draft_dir, exist_ok=True)
    
    # 保存附件（使用原文件名） - 异步执行
    file_path = os.path.join(draft_dir, file.filename)
    def write_file():
        with open(file_path, "wb") as buffer:
            buffer.write(content)
    await run_in_executor(write_file)
    
    logger.info(f"草稿 {draft_id} 附件已保存: {file_path}")
    return success(data={
        "path": file_path,
        "filename": file.filename
    }, msg="附件上传成功")